package com.ushine.design.jdk8.lambda;

/**
 * jdk8的特性：lambda表达式
 *
 * @author yls
 * <p>
 * 1、语法如下 (parameters) -> expression 或者 (parmeters) -> {statements;}
 * <p>
 * 2、重要特征： .可选类型声明：不需要声明参数类型，编译器可以统一识别参数值
 * .可选的参数圆括号：一个参数无需定义圆括号，但是多个参数需要定义圆括号 .可选的大括号：如果一个主体包含一个语句，就不需要大括号
 * .可选的返回关键字：如果一个主体只有一个表达式返回值则编译器会自动返回值，但是大括号需要指定表达式返回一个数值
 * <p>
 * 3、表达式实例 1）、不需要参数，返回值为5 () -> 5
 * <p>
 * 2）、接收一个参数（数字类型），返回其2倍的值 x -> 2*x
 * <p>
 * 3）、接收两个参数（数字），并返回它们的差值 (x , y) -> x - y
 * <p>
 * 4）、接收两个int型参数，返回它们的和 (int x , int y) -> x + y
 * <p>
 * 5）、接受一个string对象，并在控制台打印，不返回任何值（看起来像是返回void） (String str) ->
 * System.out.print(str);
 */
public class JDK8_Lambda {
    /**
     * 一个接口只能写一个方法
     */
    interface MathOperation {
        int operation(int a, int b);
    }

    interface GreetingServie {
        void sayMessage(String message);
    }

    interface Convert<T1, T2> {
        void convert(int i);
    }

    static String salution = "hello";

    public static void main(String args[]) {
        /**
         * 基本操作
         */
        getLambdaBase();

        /**
         * 变量的作用域使用
         */
        getBianLiangUse();

        /**
         * 变量的作用域使用方法
         */
        getBianLiang();
    }

    /**
     * 局部变量：final标记的外层局部变量。
     */
    private static void getBianLiangUse() {
        /**
         * 变量的作用域。只能引用了final标记的外层局部变量。
         * 也就是不能在lambda内部修饰定义在域外的局部变量，否则编译器会报错。
         */
        GreetingServie greetingServie = message -> System.out.println(salution + " " + message);
        greetingServie.sayMessage("world!");
    }


    /**
     * 局部变量：隐式的局部变量，可以不用final修饰
     */
    private static void getBianLiang() {
        /**
         * 隐式的局部变量，可以不用final修饰，但是不能被后面的代码修改，否则会报错。
         */
        int num = 20;
        Convert<Integer, String> s = (param) -> System.err.println(String.valueOf(param + num));
        s.convert(6);
        /**
         * 如果此时修改会出现以下的错误：
         * 报错：Local variable num defined in an enclosing scope must be final or effectively final
         */
        //num = 6;
    }

    /**
     * 基本实例
     */
    private static void getLambdaBase() {
        JDK8_Lambda jdk8_Lambda = new JDK8_Lambda();

        // 类型声明
        MathOperation addition = (int a, int b) -> a + b;

        // 不声明类型
        MathOperation subtraction = (a, b) -> a - b;

        // 大括号返回语句
        MathOperation multiplication = (int a, int b) -> {
            return a * b;
        };

        // 没有大括号以及返回语句
        MathOperation divsion = (int a, int b) -> a / b;

        System.out.println("10 + 5 = " + jdk8_Lambda.operation(10, 5, addition));
        System.out.println("10 - 5 = " + jdk8_Lambda.operation(10, 5, subtraction));
        System.out.println("10 * 5 = " + jdk8_Lambda.operation(10, 5, multiplication));
        System.out.println("10 / 5 = " + jdk8_Lambda.operation(10, 5, divsion));

        GreetingServie greetingServie1 = message -> System.out.println(message);
        greetingServie1.sayMessage("JDK8");

        GreetingServie greetingServie2 = (message) -> System.out.println(message);
        greetingServie2.sayMessage("JDK8-002");
    }

    private int operation(int a, int b, MathOperation mathOperation) {
        return mathOperation.operation(a, b);
    }


}
